home *** CD-ROM | disk | FTP | other *** search
/ Atari Forever 4 / Atari Forever 4.zip / Atari Forever 4.iso / PD_THEMA / GESETZE / LHARC.221 / DOC / ALGORITH.DOC next >
Text File  |  1993-03-16  |  14KB  |  295 lines

  1.                                                            April 7, 1989
  2.  
  3. ------------------------------------------------------------------------
  4.              Data Compression Algorithms of LARC and LHarc
  5.                            Haruhiko Okumura*
  6.  
  7.        * The author is the Sysop of the Science SIG of PV-VAN.  His
  8.          address is: 12-2-404 Green Heights, 580 Nagasawa, Yokosuka
  9.          239, Japan
  10. ------------------------------------------------------------------------
  11.  
  12. 1. Introduction
  13.  
  14.    In the spring of 1988, I wrote a very simple data compression program
  15.    named LZSS in C language, and uploaded it to the Science SIG (forum)
  16.    of PC-VAN, Japan's biggest personal computer network.
  17.  
  18.    That program was based on Storer and Szymanski's slightly modified
  19.    version of one of Lempel and Ziv's algorithms.  Despite its simplic-
  20.    ity, for most files its compression outperformed the archivers then
  21.    widely used.
  22.  
  23.    Kazuhiko Miki rewrote my LZSS in Turbo Pascal and assembly language,
  24.    and soon made it evolve into a complete archiver, which he named
  25.    LARC.
  26.  
  27.    The first versions of LZSS and LARC were rather slow.  So I rewrote
  28.    my LZSS using a binary tree, and so did Miki.  Although LARC's
  29.    encoding was slower than the fastest archiver available, its decoding
  30.    was quite fast, and its algorithm was so simple that even self-
  31.    extracting files (compressed files plus decoder) it created were
  32.    usually smaller than non-self-extracting files from other archivers.
  33.  
  34.    Soon many hobby programmers joined the archiver project at the forum.
  35.    Very many suggestions were made, and LARC was revised again and
  36.    again.  By the summer of 1988, LARC's speed and compression have
  37.    improved so much that LARC-compressed programs were beginning to be
  38.    uploaded in many forums of PC-VAN and other networks.
  39.  
  40.    In that summer I wrote another program, LZARI, which combined the
  41.    LZSS algorithm with adaptive arithmetic compression.  Although it was
  42.    slower than LZSS, its compression performance was amazing.
  43.  
  44.    Miki, the author of LARC, uploaded LZARI to NIFTY-Serve, another big
  45.    information network in Japan.  In NIFTY-Serve, Haruyasu Yoshizaki
  46.    replaced LZARI's adaptive arithmetic coding with a version of
  47.    adaptive Huffman coding to increase speed.  Based on this algorithm,
  48.    which he called LZHUF, he developed yet another archiver, LHarc.
  49.  
  50.    In what follows, I will review several of these algorithms and supply
  51.    simplified codes in C language.
  52.  
  53.  
  54. 2. Simple coding methods
  55.  
  56.    Replacing several (usually 8 or 4) "space" characters by one "tab"
  57.    character is a very primitive method for data compression.  Another
  58.    simple method is run-length coding, which encodes the message
  59.    "AAABBBBAACCCC" into "3A4B2A4C", for example.
  60.  
  61.  
  62. 3. LZSS coding
  63.  
  64.    This scheme is initiated by Ziv and Lempel [1].  A slightly modified
  65.    version is described by Storer and Szymanski [2].  An implementation
  66.    using a binary tree is proposed by Bell [3].  The algorithm is quite
  67.    simple: Keep a ring buffer, which initially contains "space"
  68.    characters only.  Read several letters from the file to the buffer.
  69.    Then search the buffer for the longest string that matches the
  70.    letters just read, and send its length and position in the buffer.
  71.  
  72.    If the buffer size is 4096 bytes, the position can be encoded in 12
  73.    bits.  If we represent the match length in four bits, the <position,
  74.    length> pair is two bytes long.  If the longest match is no more than
  75.    two characters, then we send just one character without encoding, and
  76.    restart the process with the next letter.  We must send one extra bit
  77.    each time to tell the decoder whether we are sending a <position,
  78.    length> pair or an unencoded character.
  79.  
  80.    The accompanying file LZSS.C is a version of this algorithm.  This
  81.    implementation uses multiple binary trees to speed up the search for
  82.    the longest match.  All the programs in this article are written in
  83.    draft-proposed ANSI C.  I tested them with Turbo C 2.0.
  84.  
  85.  
  86. 4. LZW coding
  87.  
  88.    This scheme was devised by Ziv and Lempel [4], and modified by Welch
  89.    [5].
  90.  
  91.    The LZW coding has been adopted by most of the existing archivers,
  92.    such as ARC and PKZIP.  The algorithm can be made relatively fast,
  93.    and is suitable for hardware implementation as well.
  94.  
  95.    The algorithm can be outlined as follows: Prepare a table that can
  96.    contain several thousand items.  Initially register in its 0th
  97.    through 255th positions the usual 256 characters.  Read several
  98.    letters from the file to be encoded, and search the table for the
  99.    longest match.  Suppose the longest match is given by the string
  100.    "ABC".  Send the position of "ABC" in the table.  Read the next
  101.    character from the file.  If it is "D", then register a new string
  102.    "ABCD" in the table, and restart the process with the letter "D".  If
  103.    the table becomes full, discard the oldest item or, preferably, the
  104.    least used.  A Pascal program for this algorithm is given in Storer's
  105.    book [6].
  106.  
  107.  
  108. 5. Huffman coding
  109.  
  110.    Classical Huffman coding is invented by Huffman [7].  A fairly
  111.    readable accound is given in Sedgewick [8].  Suppose the text to be
  112.    encoded is "ABABACA", with four A's, two B's, and a C.  We represent
  113.    this situation as follows:
  114.  
  115.                         4    2    1
  116.                         |    |    |
  117.                         A    B    C
  118.  
  119.    Combine the least frequent two characters into one, resulting in the
  120.    new frequency 2 + 1 = 3:
  121.  
  122.                         4      3
  123.                         |     /  \
  124.                         A    B    C
  125.  
  126.    Repeat the above step until the whole characters combine into a tree:
  127.  
  128.                             7
  129.                           /  \
  130.                          /     3
  131.                         /    /  \
  132.                        A    B    C
  133.  
  134.    Start at the top ("root") of this encoding tree, and travel to the
  135.    character you want to encode.  If you go left, send a "0"; otherwise
  136.    send a "1".  Thus, "A" is encoded by "0", "B" by "10", "C" by "11".
  137.    Algotether, "ABABACA" will be encoded into ten bits, "0100100110".
  138.  
  139.    To decode this code, the decoder must know the encoding tree, which
  140.    must be sent separately.
  141.  
  142.    A modification to this classical Huffman coding is the adaptive, or
  143.    dynamic, Huffman coding.  See, e.g., Gallager [9].  In this method,
  144.    the encoder and the decoder processes the first letter of the text as
  145.    if the frequency of each character in the file were one, say.  After
  146.    the first letter has been processed, both parties increment the
  147.    frequency of that character by one.  For example, if the first letter
  148.    is 'C', then freq['C'] becomes two, whereas every other frequencies
  149.    are still one.  Then the both parties modify the encoding tree
  150.    accordingly.  Then the second letter will be encoded and decoded, and
  151.    so on.
  152.  
  153. 6. Arithmetic coding
  154.  
  155.    The original concept of arithmetic coding is proposed by P. Elias.
  156.    An implementation in C language is described by Witten and others
  157.    [10].
  158.  
  159.    Although the Huffman coding is optimal if each character must be
  160.    encoded into a fixed (integer) number of bits, arithmetic coding wins
  161.    if no such restriction is made.  As an example we shall encode "AABA"
  162.    using arithmetic coding.  For simplicity suppose we know beforehand
  163.    that the probabilities for "A" and "B" to appear in the text are 3/4
  164.    and 1/4, respectively.
  165.  
  166.    Initially, consider an interval:
  167.  
  168.                         0 <= x < 1
  169.  
  170.    Since the first character is "A" whose probability is 3/4, we shrink
  171.    the interval to the lower 3/4:
  172.  
  173.                         0 <= x < 3/4
  174.  
  175.    The next character is "A" again, so we take the lower 3/4:
  176.  
  177.                         0 <= x < 9/16
  178.  
  179.    Next comes "B" whose probability is 1/4, so we take the upper 1/4:
  180.  
  181.                         27/64 <= x < 9/16
  182.  
  183.    because "B" is the second element in our alphabet, {A, B}.  The last
  184.    character is "A" and the interval is:
  185.  
  186.                         27/64 <= x < 135/256
  187.  
  188.    which can be written in binary notation:
  189.  
  190.                         0.011011 <= x < 0.10000111
  191.  
  192.    Choose from this interval any number that can be represented in
  193.    fewest bits, say 0.1, and send the bits to the right of "0."; in this
  194.    case we send only one bit, "1".  Thus we have encoded four letters
  195.    into one bit!  With the Huffman coding, four letters could not be
  196.    encoded into less than four bits.
  197.  
  198.    To decode the code "1", we just reverse the process: First, we supply
  199.    the "0." to the right of the received code "1", resulting in "0.1" in
  200.    binary notation, or 1/2.  Since this number is in the first 3/4 of
  201.    the initial interval 0 <= x < 1, the first character must be "A".
  202.    Shrink the interval into the lower 3/4.  In this new interval, the
  203.    number 1/2 lies in the lower 3/4 part, so the second character is
  204.    again "A", and so on.  The number of letters in the original file
  205.    must be sent separately (or a special 'EOF' character must be ap-
  206.    pended at the end of the file).
  207.  
  208.    The algorithm described above requires that both the sender and
  209.    receiver know the probability distribution for the characters.  The
  210.    adaptive version of the algorithm removes this restriction by first
  211.    supposing uniform or any agreed-upon distribution of characters that
  212.    approximates the true distribution, and then updating the
  213.    distribution after each character is sent and received.
  214.  
  215.  
  216. 7. LZARI
  217.  
  218.    In each step the LZSS algorithm sends either a character or a
  219.    <position, length> pair.  Among these, perhaps character "e" appears
  220.    more frequently than "x", and a <position, length> pair of length 3
  221.    might be commoner than one of length 18, say.  Thus, if we encode the
  222.    more frequent in fewer bits and the less frequent in more bits, the
  223.    total length of the encoded text will be diminished.  This
  224.    consideration suggests that we use Huffman or arithmetic coding,
  225.    preferably of adaptive kind, along with LZSS.
  226.  
  227.    This is easier said than done, because there are many possible
  228.    <position, length> combinations.  Adaptive compression must keep
  229.    running statistics of frequency distribution.  Too many items make
  230.    statistics unreliable.
  231.  
  232.    What follows is not even an approximate solution to the problem posed
  233.    above, but anyway this was what I did in the summer of 1988.
  234.  
  235.    I extended the character set from 256 to three-hundred or so in size,
  236.    and let characters 0 through 255 be the usual 8-bit characters,
  237.    whereas characters 253 + n represent that what follows is a position
  238.    of string of length n, where n = 3, 4 ....  These extended set of
  239.    characters will be encoded with adaptive arithmetic compression.
  240.  
  241.    I also observed that longest-match strings tend to be the ones that
  242.    were read relatively recently.  Therefore, recent positions should be
  243.    encoded into fewer bits.  Since 4096 positions are too many to encode
  244.    adaptively, I fixed the probability distribution of the positions "by
  245.    hand." The distribution function given in the accompanying LZARI.C
  246.    is rather tentative; it is not based on thorough experimentation.  In
  247.    retrospect, I could encode adaptively the most significant 6 bits,
  248.    say, or perhaps by some more ingenious method adapt the parameters of
  249.    the distribution function to the running statistics.
  250.  
  251.    At any rate, the present version of LZARI treats the positions rather
  252.    separately, so that the overall compression is by no means optimal.
  253.    Furthermore, the string length threshold above which strings are
  254.    coded into <position, length> pairs is fixed, but logically its value
  255.    must change according to the length of the <position, length> pair we
  256.    would get.
  257.  
  258.  
  259. 8. LZHUF
  260.  
  261.    LZHUF, the algorithm of Haruyasu Yoshizaki's archiver LHarc, replaces
  262.    LZARI's adaptive arithmetic coding with adaptive Huffman.  LZHUF
  263.    encodes the most significant 6 bits of the position in its 4096-byte
  264.    buffer by table lookup.  More recent, and hence more probable,
  265.    positions are coded in less bits.  On the other hand, the remaining 6
  266.    bits are sent verbatim.  Because Huffman coding encodes each letter
  267.    into a fixed number of bits, table lookup can be easily implemented.
  268.  
  269.    Though theoretically Huffman cannot exceed arithmetic compression,
  270.    the difference is very slight, and LZHUF is fairly fast.
  271.  
  272.    The LZHUF.C file was written by Yoshizaki.  I translated the comments
  273.    into English and made a few trivial changes to make it conform to the
  274.    ANSI C standard.
  275.  
  276.  
  277. References
  278.  
  279.       [1] J. Ziv and A. Lempel, IEEE Trans. IT-23, 337-343 (1977).
  280.       [2] J. A. Storer and T. G. Szymanski, J. ACM, 29, 928-951
  281.           (1982).
  282.       [3] T. C. Bell, IEEE Trans. COM-34, 1176-1182 (1986).
  283.       [4] J. Ziv and A. Lempel, IEEE Trans. IT-24, 530-536 (1978).
  284.       [5] T. A. Welch, Computer, 17, No.6, 8-19 (1984).
  285.       [6] J. A. Storer, Data Compression: Methods and Theory
  286.           (Computer Science Press, 1988).
  287.       [7] D. A. Huffman, Proc IRE 40, 1098-1101 (1952).
  288.       [8] R. Sedgewick, Algorithms, 2nd ed. (Addison-Wesley, 1988).
  289.       [9] R. G. Gallager, IEEE Trans. IT-24, 668-674 (1978).
  290.      [10] I. E. Witten, R. M. Neal, and J. G. Cleary, Commun. ACM
  291.           30, 520-540 (1987).
  292.  
  293.                                 - end -
  294.  
  295.